#include "MVData.h"
#include "MVDataBlock.h"
#include "MVDataBlockP.h"
#include "MVDataBlockB.h"
#include "MVDataBlockI.h"

CMVDataBlock::CMVDataBlock( const CMVDataBlock& block ) : CMVDataMBCommon( static_cast<const CMVDataMBCommon>( block ) )
{
	m_pMB = block.m_pMB;
	m_eFirstLayerLoc = block.m_eFirstLayerLoc;
	m_eSecondLayerLoc = block.m_eSecondLayerLoc;
	m_eBlockType = block.m_eBlockType;
	m_eSubMBType = block.m_eSubMBType;
}

CMVDataBlock * CMVDataBlock::CreateBlock( TYPE_BLOCK block_type )
{

	switch ( block_type )
	{
	case TYPE_BLOCK_P:
		return new CMVDataBlockP();
		break;
	case TYPE_BLOCK_B:
		return new CMVDataBlockB();
		break;
	case TYPE_BLOCK_I:
		return new CMVDataBlockI();
		break;
	default:
		return NULL;
		break;
	}

	return NULL;
}


CMVDataBlock::CMVDataBlock( TYPE_BLOCK block_type )
{
	m_pMB = NULL;
	m_eBlockType = block_type;
	m_eFirstLayerLoc = LOC_BLOCK_NO_USE;
	m_eSecondLayerLoc = LOC_BLOCK_NO_USE;
	m_eSubMBType = TYPE_SUB_MB_NO_USE;
}

CMVDataBlock& CMVDataBlock::operator =( const CMVDataBlock& block )
{

	static_cast<CMVDataMBCommon>( *this ) = static_cast<CMVDataMBCommon>( block );
	m_pMB = block.m_pMB;
	m_eBlockType = block.m_eBlockType;
	m_eFirstLayerLoc = block.m_eFirstLayerLoc;
	m_eSecondLayerLoc = block.m_eSecondLayerLoc;
	m_eSubMBType = block.m_eSubMBType;

	return *this;
}

LOC_BLOCK CMVDataBlock::GetFirstLayerLoc() const
{
	return m_eFirstLayerLoc;
}

int CMVDataBlock::SetFirstLayerLoc( LOC_BLOCK first_layer_loc )
{
	m_eFirstLayerLoc = first_layer_loc;
	return 0;	
}

LOC_BLOCK CMVDataBlock::GetSecondLayerLoc() const
{
	return m_eSecondLayerLoc;
}

int CMVDataBlock::SetSecondLayerLoc( LOC_BLOCK second_layer_loc )
{
	m_eSecondLayerLoc = second_layer_loc;
	return 0;
}

int CMVDataBlock::SetAllLayerLoc( LOC_BLOCK first_layer_loc, LOC_BLOCK second_layer_loc )
{
	m_eFirstLayerLoc = first_layer_loc;
	m_eSecondLayerLoc = second_layer_loc;
	return 0;
}

TYPE_BLOCK CMVDataBlock::GetBlockType() const
{
	return m_eBlockType;
}
bool CMVDataBlock::IsValid() const
{

	// the first layer location must be used.
	if( m_eFirstLayerLoc == LOC_BLOCK_NO_USE )
	{
		return false;
	}

	// a 8x8 sub macro block
	if ( m_eFirstLayerLoc == LOC_BLOCK_UPLEFT || m_eFirstLayerLoc == LOC_BLOCK_UPRIGHT 
		|| m_eFirstLayerLoc == LOC_BLOCK_DOWNRIGHT || m_eFirstLayerLoc == LOC_BLOCK_DOWNLEFT )
	{
		// the second layer location should be used in a 8x8 sub macro block
		if ( m_eSecondLayerLoc == LOC_BLOCK_NO_USE )
		{
			return false;
		}
	}


	if( !HaveMVCoordinate() )
	{
		return false;
	}

	return true;
}


SHAPE_BLOCK CMVDataBlock::GetShape() const
{
	if( GetFirstLayerLoc() == LOC_BLOCK_FULL )
	{
		return SHAPE_BLOCK_MB;
	}
	else if( GetFirstLayerLoc() == LOC_BLOCK_LEFT || GetFirstLayerLoc() == LOC_BLOCK_RIGHT ||
		GetFirstLayerLoc() == LOC_BLOCK_UP || GetFirstLayerLoc() == LOC_BLOCK_DOWN )
	{
		return SHAPE_BLOCK_SUB_MB;
	}
	else if ( GetFirstLayerLoc() == LOC_BLOCK_DOWNLEFT || GetFirstLayerLoc() == LOC_BLOCK_UPLEFT ||
		GetFirstLayerLoc() == LOC_BLOCK_UPRIGHT || GetFirstLayerLoc() == LOC_BLOCK_DOWNRIGHT )
	{
		if( GetSecondLayerLoc() == LOC_BLOCK_FULL )
		{
			return SHAPE_BLOCK_SUB_MB;
		}
		else
		{
			return SHAPE_BLOCK_SUB_SUB_MB;
		}
	}
	else
	{
		return SHAPE_BLOCK_NO_USE;
	}

}

const CMVDataMB * CMVDataBlock::GetMB() const
{
	return m_pMB;

}

int CMVDataBlock::SetMB( const CMVDataMB * mb )
{
	m_pMB = mb;
	return 0;
}


int CMVDataBlock::CopyDataFrom( const CMVDataMBCommon * pCommon )
{
	if( pCommon == NULL )
	{
		return -1;
	}

	// TODO 优化拷贝
	if( pCommon->HaveASAD() ) SetASAD( pCommon->GetASAD() );
	if( pCommon->HaveSADBitCount() ) SetSADBitCount( pCommon->GetSADBitCount() );
	if( pCommon->HaveMVCoordinate() ) SetMVCoordinate( pCommon->GetMVCoordinateX(), pCommon->GetMVCoordinateY() );
	if ( pCommon->HaveSubMBType() ) SetSubMBType( pCommon->GetSubMBType() );
	return 0;
}

